From 0f30bdcf5fd6064b9697686974d6a4439eb1233f Mon Sep 17 00:00:00 2001 From: "kaf24@localhost.localdomain" Date: Thu, 28 Dec 2006 16:33:15 +0000 Subject: [PATCH] [HVM] Fix assumptions that ISA IRQ 0 connects to GSI 0. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/irq.c | 28 +++++++++++++++------------- xen/arch/x86/hvm/vioapic.c | 4 ++-- xen/arch/x86/hvm/vpt.c | 27 +++++++++++++++------------ xen/include/asm-x86/hvm/irq.h | 9 ++++++--- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index e9f975eb53..1b51f5905c 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -85,7 +85,7 @@ void hvm_isa_irq_assert( struct domain *d, unsigned int isa_irq) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - unsigned int gsi = (isa_irq == 0) ? 2 : isa_irq; + unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); ASSERT(isa_irq <= 15); @@ -105,7 +105,7 @@ void hvm_isa_irq_deassert( struct domain *d, unsigned int isa_irq) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - unsigned int gsi = (isa_irq == 0) ? 2 : isa_irq; + unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); ASSERT(isa_irq <= 15); @@ -257,23 +257,25 @@ int cpu_get_interrupt(struct vcpu *v, int *type) return -1; } -int get_intr_vector(struct vcpu* v, int irq, int type) +int get_isa_irq_vector(struct vcpu *v, int isa_irq, int type) { + unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); + if ( type == APIC_DM_EXTINT ) - return v->domain->arch.hvm_domain.irq.vpic[irq >> 3].irq_base - + (irq & 0x7); + return (v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].irq_base + + (isa_irq & 7)); - return domain_vioapic(v->domain)->redirtbl[irq].fields.vector; + return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector; } -int is_irq_masked(struct vcpu *v, int irq) +int is_isa_irq_masked(struct vcpu *v, int isa_irq) { - if ( is_lvtt(v, irq) ) - return !is_lvtt_enabled(v); + unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); - if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7)) - && domain_vioapic(v->domain)->redirtbl[irq].fields.mask ) - return 1; + if ( is_lvtt(v, isa_irq) ) + return !is_lvtt_enabled(v); - return 0; + return ((v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].imr & + (1 << (isa_irq & 7))) && + domain_vioapic(v->domain)->redirtbl[gsi].fields.mask); } diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index f986d5ca1d..843c76a6dd 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -341,7 +341,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq) { #ifdef IRQ0_SPECIAL_ROUTING /* Force round-robin to pick VCPU 0 */ - if ( irq == 0 ) + if ( irq == hvm_isa_irq_to_gsi(0) ) { v = vioapic_domain(vioapic)->vcpu[0]; target = v ? vcpu_vlapic(v) : NULL; @@ -374,7 +374,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq) deliver_bitmask &= ~(1 << bit); #ifdef IRQ0_SPECIAL_ROUTING /* Do not deliver timer interrupts to VCPU != 0 */ - if ( (irq == 0) && (bit != 0) ) + if ( irq == hvm_isa_irq_to_gsi(0) ) v = vioapic_domain(vioapic)->vcpu[0]; else #endif diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index cb320bb897..12e8999582 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -108,16 +108,18 @@ void pt_update_irq(struct vcpu *v) list_for_each( list, head ) { pt = list_entry(list, struct periodic_time, list); - if ( !is_irq_masked(v, pt->irq) && pt->pending_intr_nr - && pt->last_plt_gtime + pt->period < max_lag ) + if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr && + ((pt->last_plt_gtime + pt->period_cycles) < max_lag) ) { - max_lag = pt->last_plt_gtime + pt->period; + max_lag = pt->last_plt_gtime + pt->period_cycles; irq = pt->irq; } } if ( is_lvtt(v, irq) ) + { vlapic_set_irq(vcpu_vlapic(v), irq, 0); + } else if ( irq >= 0 ) { hvm_isa_irq_deassert(v->domain, irq); @@ -141,16 +143,15 @@ struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type) if ( is_lvtt(v, pt->irq) ) { - if (pt->irq == vector) - return pt; - else + if ( pt->irq != vector ) continue; + return pt; } - vec = get_intr_vector(v, pt->irq, type); + vec = get_isa_irq_vector(v, pt->irq, type); /* RTC irq need special care */ - if ( vector != vec || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) ) + if ( (vector != vec) || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) ) continue; return pt; @@ -163,14 +164,14 @@ void pt_intr_post(struct vcpu *v, int vector, int type) { struct periodic_time *pt = is_pt_irq(v, vector, type); - if (pt == NULL) + if ( pt == NULL ) return; pt->pending_intr_nr--; pt->last_plt_gtime += pt->period_cycles; hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime); - if (pt->cb) + if ( pt->cb != NULL ) pt->cb(pt->vcpu, pt->priv); } @@ -200,9 +201,11 @@ void create_periodic_time(struct periodic_time *pt, uint64_t period, destroy_periodic_time(pt); pt->enabled = 1; - if (period < 900000) /* < 0.9 ms */ + if ( period < 900000 ) /* < 0.9 ms */ { - printk("HVM_PlatformTime: program too small period %"PRIu64"\n", period); + gdprintk(XENLOG_WARNING, + "HVM_PlatformTime: program too small period %"PRIu64"\n", + period); period = 900000; /* force to 0.9ms */ } pt->period = period; diff --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h index 85e3d3fa88..af66d67f2c 100644 --- a/xen/include/asm-x86/hvm/irq.h +++ b/xen/include/asm-x86/hvm/irq.h @@ -61,7 +61,8 @@ struct hvm_irq { /* * Number of wires asserting each GSI. * - * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space. + * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space + * except ISA IRQ 0, which is connected to GSI 2. * PCI links map into this space via the PCI-ISA bridge. * * GSIs 16+ are used only be PCI devices. The mapping from PCI device to @@ -87,6 +88,8 @@ struct hvm_irq { #define hvm_pci_intx_link(dev, intx) \ (((dev) + (intx)) & 3) +#define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2) + /* Modify state of a PCI INTx wire. */ void hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx); @@ -106,7 +109,7 @@ void hvm_set_callback_gsi(struct domain *d, unsigned int gsi); int cpu_get_interrupt(struct vcpu *v, int *type); int cpu_has_pending_irq(struct vcpu *v); -int get_intr_vector(struct vcpu* vcpu, int irq, int type); -int is_irq_masked(struct vcpu *v, int irq); +int get_isa_irq_vector(struct vcpu *vcpu, int irq, int type); +int is_isa_irq_masked(struct vcpu *v, int isa_irq); #endif /* __ASM_X86_HVM_IRQ_H__ */ -- 2.30.2